package com.sz.biz.logistics.ord.service.impl;

import com.sz.biz.common.constants.ModuleNames;
import com.sz.biz.logistics.constants.OrderNumberConstants;
import com.sz.biz.logistics.ord.entity.OrdWaybillNoManagement;
import com.sz.biz.logistics.ord.service.OrdWaybillNoManagementService;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.service.AbstractService;
import com.sz.common.core.service.PrincipalLogUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.validation.constraints.NotNull;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Package: com.sz.biz.logistics.ord.service.impl<br>
 * Description: 订单信息管理服务实现类
 * @author WuHan<br>
 * @date 2017-09-12 17:56<br>
 * @since sys-1.1.2.1
 */
@Service ("OrdWaybillNoManagementService")
public class OrdWaybillNoManagementServiceImpl
        extends AbstractService
        implements OrdWaybillNoManagementService {
    
    /**
     * 单体保存订单信息
     * @param ordWaybillNoManagement 订单信息实体类，{@link OrdWaybillNoManagement}
     * @return 插入条目成功则返回记录数
     * */
    @Override
    public int save(OrdWaybillNoManagement ordWaybillNoManagement) {
        int res = 0;
        if (!ObjectUtils.isEmpty(ordWaybillNoManagement)) {
            if (collisionDetect(ordWaybillNoManagement.getServiceType().toString(), ordWaybillNoManagement.getSerialNo())) {
                try {
                    res = dao.save(getSqlName("insert"), ordWaybillNoManagement);
                    if (0 == res) {
                        throw new SQLException("单号数据写入失败，目标：ord_waybillno_management");
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                //保存操作日志
                Map<String, Object> dataBackup = new HashMap<>();
                dataBackup.put("ADD_WAYBILL_NUMBER", ordWaybillNoManagement);
                PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_WAYBILLNO, UserActions.ADD, "添加订单编号", dataBackup);
            }
        }
        return res;
    }
    
    /**
     * 单体保存订单信息
     * @param serviceType 业务类型，见{@link com.sz.biz.logistics.ord.enums.OrdServiceTypeEnum}
     * @param serialNumber 序列号
     * @param verificationCode 校验位
     * @return 插入条目成功则返回记录数
     * @see #save(String, String, String, boolean, boolean, boolean)
     * */
    @Override
    public int save(String serviceType, String serialNumber, String verificationCode) {
        return save(serviceType, serialNumber, verificationCode, true, false, false);
    }
    
    /**
     * 单体保存订单信息
     * @param serviceType 业务类型，见{@link com.sz.biz.logistics.ord.enums.OrdServiceTypeEnum}
     * @param serialNumber 序列号
     * @param verificationCode 校验位
     * @param isUsed 已使用标记
     * @param isPrearranged 预分配标记
     * @param isDeleted 软删除标记
     * @return 插入条目成功则返回记录数
     * */
    @Override
    public int save(@NotNull String serviceType, @NotNull String serialNumber, @NotNull String verificationCode, boolean isUsed, boolean isPrearranged, boolean isDeleted) {
        OrdWaybillNoManagement ordWaybillNoManagement = new OrdWaybillNoManagement();
        ordWaybillNoManagement.setServiceType(Byte.valueOf(serviceType));
        ordWaybillNoManagement.setSerialNo(serialNumber);
        ordWaybillNoManagement.setVerificationCode(Byte.valueOf(verificationCode));
        ordWaybillNoManagement.setIsUsed(isUsed);
        ordWaybillNoManagement.setIsPrearranged(isPrearranged);
        ordWaybillNoManagement.setIsDeleted(isDeleted);
        return save(ordWaybillNoManagement);
    }
    
    /**
     * 获取三种业务类型各自当前最大已使用的非预分配单号值
     * @return 三个值，若不存在，则返回值默认为"00000000"
     * */
    @Override
    public List<String> fetchTopNumbers() {
        return dao.findForList(getSqlName("fetchTopNumbers"), null, String.class);
    }
    
    /**
     * 单号碰撞检测，用以判断将要分配的单号是否同预分配区间产生碰撞。
     * @param serviceType 业务类型，见{@link com.sz.biz.logistics.ord.enums.OrdServiceTypeEnum}
     * @param serialNumber 序列号
     * @return 是否产生碰撞。<br>True - 产生碰撞<br>False - 未产生碰撞
     * */
    @Override
    public boolean collisionDetect(String serviceType, String serialNumber) {
        boolean res = false;
        if (!StringUtils.isEmpty(serialNumber) && serialNumber.matches(
                OrderNumberConstants.RuleRegex.WAYBILLNUMBER_REGEX)) {
            ParamData pd = new ParamData();
            pd.put("serviceType", serviceType);
            pd.put("pattern", serialNumber);
            res = (Boolean) dao.findForObject(getSqlName("singleDetect"), pd);
        }
        return res;
    }
    
    
    /**
     * 号段碰撞检测，用以判断将要分配的号段是否同现有已分配号段及单号记录产生碰撞。
     * @param serviceType 业务类型，见{@link com.sz.biz.logistics.ord.enums.OrdServiceTypeEnum}
     * @param startIndex 号段起点
     * @param endIndex 号段终点
     * @return 是否产生碰撞。<br>True - 产生碰撞<br>False - 未产生碰撞
     * */
    @Override
    public boolean collisionDetect(String serviceType, String startIndex, String endIndex) {
        boolean res = false;
        if (!StringUtils.isEmpty(startIndex)
                && !StringUtils.isEmpty(endIndex)
                && Long.valueOf(endIndex) > Long.valueOf(startIndex)) {
            ParamData pd = new ParamData();
            pd.put("serviceType", serviceType);
            pd.put("startIndex", startIndex);
            pd.put("endIndex", endIndex);
            res = (Boolean) dao.findForObject(getSqlName("batchDetect"), pd);
        }
        return res;
    }
    
    @Override
    protected String getMapperNamespace() {
        return "com.sz.biz.logistics.ord.entity.OrdWaybillNoManagementMapper";
    }
}
